package com.core.image.core;

import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;
import java.util.concurrent.Executors;

public class IoArgs {
    private int limit = 256;
    private byte[] byteBuffer = new byte[limit];
    // 是否需要消费所有的区间（读取、写入）
    private final boolean isNeedConsumeRemaining;
    private ByteBuffer buffer = ByteBuffer.wrap(byteBuffer);
    public IoArgs(){
        this(256);
    }
    public IoArgs(int size){
        this(size,true);
    }

    public IoArgs(int size, boolean isNeedConsumeRemaining) {
        this.limit = size;
        this.isNeedConsumeRemaining = isNeedConsumeRemaining;
        this.buffer = ByteBuffer.allocate(size);
    }
    public boolean isNeedConsumeRemaining(){
        return isNeedConsumeRemaining;
    }

    /**
     * 从bytes中读取数据
     */
    public int readFrom(ReadableByteChannel channel)throws IOException{
              int readBuffer = 0;
        while (buffer.hasRemaining()) {
            int len = channel.read(buffer);
            if (len < 0){
                throw  new EOFException();
            }
            readBuffer += len;
        }

        return readBuffer;
    }
    /**
     * 写入数据到bytes中
     */
    public int writeTo(WritableByteChannel channel)throws IOException {
        int writeBuffer = 0;
        while (buffer.hasRemaining()) {
            int len = channel.write(buffer);
            if (len < 0) {
                throw new EOFException();
            }
            writeBuffer += len;
        }
        return writeBuffer;
    }

    public int readFrom(byte[] bytes,int offset){
        int size = Math.min(bytes.length - offset,buffer.remaining());
        buffer.put(bytes,offset,size);
        return size;
    }
    public int writeTo(byte[] bytes,int offset){
        int size = Math.min(bytes.length - offset,buffer.remaining());
        buffer.get(bytes,offset,size);
        return size;
    }
    public int readFrom(SocketChannel channel)throws Exception{
        ByteBuffer buffer = this.buffer;
        int bytesProduced = 0;
        int len;
        do {
            len = channel.read(buffer);
            if (len < 0){
                throw  new EOFException();
            }
            bytesProduced += len;

        }while (buffer.hasRemaining()&&len != 0);
        return bytesProduced;
    }

    public void finishWriting() {
        buffer.flip();
    }

    public int writeTo(SocketChannel channel) throws Exception{
        ByteBuffer buffer = this.buffer;
        int bytesProduces = 0;
        int len;
        do {
            len = channel.write(buffer);
            if (len < 0){
                throw  new EOFException();
            }
            bytesProduces += len;

        }while (buffer.hasRemaining()&&len!=0);
        return bytesProduces;
    }
    public void startWriting(){
        buffer.clear();
        // 定义容纳区间
        buffer.limit(limit);

    }
    public void limit(int limit){
        this.limit = Math.min(limit, buffer.capacity());
    }


    public int readLength(){
        return buffer.getInt();
    }
 /*   public void writeLength(int total){
        startWriting();
        buffer.putInt(total);
        finishWriting();
    }*/
    public String bufferString() {
        // 丢弃换行符
        return new String(byteBuffer, 0, buffer.position() - 1);
    }

    public int capacity() {
        return buffer.capacity();
    }

    public boolean remained() {
        return buffer.remaining()>0;
    }

    public int readFrom(byte[] bytes, int offset, int count) {
        int size = Math.min(count, buffer.remaining());
        if (size <= 0) {
            return 0;
        }
        buffer.put(bytes, offset, size);
        return size;
    }

    /**
     * 填充数据
     *
     * @param size 想要填充数据的长度
     * @return 真实填充数据的长度
     */
    public int fillEmpty(int size) {
        int fillSize = Math.min(size,buffer.remaining());
        buffer.position(buffer.position()+fillSize);
        return fillSize;
    }

    public int setEmpty(int size) {
        int emptySize = Math.min(size, buffer.remaining());
        buffer.position(buffer.position() + emptySize);
        return emptySize;
    }

    public void resetLimit() {
        this.limit = buffer.capacity();
    }

    public interface IoArgsEventProcessor {
        /**
         * 提供一份消費的IoArgs
         * @return
         */
      IoArgs provideIoArgs();

        /**
         *消费失败
         * @param ioArgs
         * @param e 异常信息
         */
      void onConsumeFailed(IoArgs ioArgs, Exception e);

        /**
         * 消费成功。
         * @param ioArgs
         */
      void onConsumeComplete(IoArgs ioArgs);
    }
}
